package com.example.my_gobang.game;

import com.example.my_gobang.MyGobangApplication;
import com.example.my_gobang.mapper.UserMapper;
import com.example.my_gobang.model.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.UUID;

/**
 * Creat with IntelliJ IDEA
 * Description:一个游戏房间
 * User:WZW
 * Date:2022-08-22
 * Time:16:53
 */

public class Room {
    private String roomId;

    private User user1;
    private User user2;

    //先手玩家id
    private int whiteUser;

    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;

    public int getWhiteUser() {
        return whiteUser;
    }

    public void setWhiteUser(int whiteUser) {
        this.whiteUser = whiteUser;
    }

    public String getRoomId() {
        return roomId;
    }

    public void setRoomId(String roomId) {
        this.roomId = roomId;
    }

    public User getUser1() {
        return user1;
    }

    public void setUser1(User user1) {
        this.user1 = user1;
    }

    public User getUser2() {
        return user2;
    }

    public void setUser2(User user2) {
        this.user2 = user2;
    }

    public Room() {
        // 生成一个唯一的字符串表示房间id
        roomId = UUID.randomUUID().toString();
        // 通过入口来中记录的context手动获取spring管理的实例对象
        onlineUserManager = MyGobangApplication.context.getBean(OnlineUserManager.class);
        roomManager = MyGobangApplication.context.getBean(RoomManager.class);
        userMapper = MyGobangApplication.context.getBean(UserMapper.class);
    }

    // 棋盘数组，0表示未落子
    // 1表示玩家1的落子位置
    // 2表示玩家2的落子位置
    private int[][] board = new int[MAX_ROW][MAX_COL];
    private ObjectMapper objectMapper = new ObjectMapper();

    private OnlineUserManager onlineUserManager;
    private RoomManager roomManager;
    private UserMapper userMapper;

    // 处理落子操作

    public void putChess(String req) throws IOException {
        // 1.记录当前落子的位置
        GameRequest request = objectMapper.readValue(req, GameRequest.class);
        GameResponse response = new GameResponse();
        // 根据落子选手进行填数
        int chess = request.getUserId() == user1.getUserid() ? 1 : 2;
        int row = request.getRow();
        int col = request.getCol();
        if (board[row][col] != 0) {
            System.out.println("当前位置(" + row + "," + col + ")已经有子了！");
            return;
        }
        board[row][col] = chess;
        // 打印棋盘信息，方便验证胜负判定
        printBoard();

        // 2.进行胜负判定
        int winner = checkWinner(row, col, chess);

        // 3.返回响应给客户端
        response.setMessage("putChess");
        response.setUserId(request.getUserId());
        response.setRow(row);
        response.setCol(col);
        response.setWinner(winner);

        WebSocketSession session1 = onlineUserManager.getFromGameRoom(user1.getUserid());
        WebSocketSession session2 = onlineUserManager.getFromGameRoom(user2.getUserid());
        if (session1 == null) {
            // 玩家1 已经下线，认为玩家2获胜
            response.setWinner(user2.getUserid());
            System.out.println("玩家1 掉线！");
        }
        if (session2 == null) {
            response.setWinner(user1.getUserid());
            System.out.println("玩家2 掉线！");
        }

        String respJson = objectMapper.writeValueAsString(response);
        if (session1 != null) {
            session1.sendMessage(new TextMessage(respJson));
        }
        if (session2 != null) {
            session2.sendMessage(new TextMessage(respJson));
        }

        if (response.getWinner() != 0) {
            // 胜负已分
            // 销毁房间
            roomManager.remove(roomId, user1.getUserid(), user2.getUserid());
            // 记录用户场次和分数信息
            int winUserId = response.getWinner();
            int loseUserId = response.getWinner() == user1.getUserid() ? user2.getUserid() : user1.getUserid();
            userMapper.userWin(winUserId);
            userMapper.userLose(loseUserId);
            System.out.println("游戏结束，房间已经销毁！获胜方为：" + response.getWinner());
        }

    }

    private void printBoard() {
        System.out.println("打印棋盘信息" + roomId);
        System.out.println("=========================================================");
        for (int r = 0; r < MAX_ROW; r++) {
            for (int c = 0; c < MAX_COL; c++) {
                System.out.print(board[r][c] + " ");
            }
            System.out.println();
        }
        System.out.println("=========================================================");

    }

    // 判定胜负
    // 若分出胜负，则返回获胜玩家的userId，否则返回0
    private int checkWinner(int row, int col, int chess) {
        // 1.检查所有的行
        for (int c = col - 4; c <= col; c++) {
            // 针对其中的一种情况，来判定这五个子是不是连在一起 && 颜色一样
            try {
                if (board[row][c] == chess
                        && board[row][c+1] == chess
                        && board[row][c+2] == chess
                        && board[row][c+3] == chess
                        && board[row][c+4] == chess) {
                    return chess == 1 ? user1.getUserid() : user2.getUserid();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }
        // 2.检查所有的列
        for (int r = row - 4; r <= row; r++) {
            try {
                if (board[r][col] == chess
                        && board[r+1][col] == chess
                        && board[r+2][col] == chess
                        && board[r+3][col] == chess
                        && board[r+4][col] == chess) {
                    return chess == 1 ? user1.getUserid() : user2.getUserid();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }
        // 3.\
        for (int r = row - 4, c = col - 4; r <= row && c <= col; r++, c++) {
            try {
                if (board[r][c] == chess
                        && board[r+1][c+1] == chess
                        && board[r+2][c+2] == chess
                        && board[r+3][c+3] == chess
                        && board[r+4][c+4] == chess) {
                    return chess == 1 ? user1.getUserid() : user2.getUserid();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }
        // 4./
        for (int r = row - 4, c = col + 4; r <= row && c >= col; r++, c--) {
            try {
                if (board[r][c] == chess
                        && board[r+1][c-1] == chess
                        && board[r+2][c-2] == chess
                        && board[r+3][c-3] == chess
                        && board[r+4][c-4] == chess) {
                    return chess == 1 ? user1.getUserid() : user2.getUserid();
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                continue;
            }
        }
        //胜负未分
        return 0;
    }
}
